﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace CSharp
{

    //让之前的双向链表，能够：被foreach迭代
    //调用扩展方法Max()：能够返回之前双向链表中存贮着最大值的节点
    //public static int Max<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector);

    public class DLinkNode<T> : IEnumerable<DLinkNode<T>>
    //IEnumerable<>尖括号代表元素类型，指明foreach里面var的元素类型是DLinkNode<T>
    {
        public DLinkNode<T> Previous { get; set; }
        public DLinkNode<T> Next { get; set; }
        public T Value { get; set; }

        IEnumerator IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }
        public IEnumerator<DLinkNode<T>> GetEnumerator()
        {
            return new Enumerator<T>(this);
        }

        public struct Enumerator<T> : IEnumerator<DLinkNode<T>>
        {
            private DLinkNode<T> _current;
            private DLinkNode<T> _tail;

            public DLinkNode<T> Current
            {
                get { return _current.Previous; }
            }

            object IEnumerator.Current => throw new NotImplementedException();
            public Enumerator(DLinkNode<T> node)
            {
                _current = node;
                _tail = new DLinkNode<T>();
            }
            public bool MoveNext()
            {
                if (_current.Next == null)
                {
                    if (_tail == _current)
                    {
                        return false;
                    }
                    _current.AddAfter(_tail);
                }
                _current = _current.Next;
                return true;
            }


            public void Dispose()
            {
                _tail = null;
                //_tail.Next.Previous = null;
            }
            public void Reset()
            {
                throw new NotImplementedException();
            }
        }



        //public void AddBefore(DLinkNode thisNext)
        //{
        //    throw new NotImplementedException();
        //}
        public void AddAfter(DLinkNode<T> node)
        {
            if (this.Next == null)
            {
                //this是尾部的情况  后面加节点node
                node.Previous = this;
                this.Next = node;
            }
            else
            {
                //node是插入的节点 this是头部 this.Next是尾部  1 [3] 2
                node.Next = this.Next;//先改插入的节点
                node.Previous = this;
                this.Next.Previous = node;//顺序不能错
                this.Next = node;
            }
        }
        //node3.InsertAfter(node1); 场景
        public void InsertAfter(DLinkNode<T> node)//在某个节点后插入
        {
            node.Previous = this;
            this.Next = node;
        }
        public void InsertBefore(DLinkNode<T> node)//在某个节点前插入
        {
            if (this.Previous == null)//[2] 1
            {
                node.Next = this;
                this.Previous = node;
            }
            else//2 [3] 1
            {
                node.Previous = this.Previous;
                node.Next = this;
                this.Previous.Next = node;
                this.Previous = node;

            }
        }
        public void Delete()
        {

            //// [1] 2 3 4 5
            //if (this.Previous == null)
            //{
            //    this.Next.Previous = null;

            //}
            //// 1 2 3 4 [5]
            //else if (this.Next == null)
            //{
            //    this.Previous.Next = null;
            //}
            //else
            //{
            //    // 1 2 [3] 4 5
            //    this.Previous.Next = this.Next;
            //    this.Next.Previous = this.Previous;
            //    //this.Next = this.Next;
            //    //node.Previous = this;
            //    //this.Next.Previous = node;
            //    //this.Next = node;
            //}

            if (this.Previous != null)
            {
                this.Previous.Next = this.Next;
            }//else 
            if (this.Next != null)
            {
                this.Next.Previous = this.Previous;
            }
            this.Previous = null;
            this.Next = null;

        }

        //public void Swap(DLinkNode node)
        //{

        //}


    }
}




